From: Jonas Dreßler Date: Thu, 24 Jul 2025 16:27:29 +0000 (+0200) Subject: st/theme-context: Run dispose on theme nodes on theme context changes X-Git-Tag: archive/raspbian/50.5-1+rpi1~1^2~104^2^2~3 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=41758311d1df0f40ae969b8d57cf3302ad2a5803;p=gnome-shell.git st/theme-context: Run dispose on theme nodes on theme context changes When the theme context changes, we clear the theme cache and make the widget tree throw away and create new theme nodes. That's because the old theme nodes can no longer be used, they might be referencing old CSS data, scale factors, or other things. St itself should never reuse theme nodes after theme context changes, but of course theme nodes are exposed to users of St, and they can always keep a theme node around and call a method on it even after a theme context change. To avoid those outdated theme nodes accessing outdated pointers into the Croco structures and causing crashes, force-run their `dispose()` function when the theme context changes. This should ensure that all problematic pointers in the theme nodes are cleared, and users of St can't crash gnome-shell. Part-of: --- diff --git a/src/st/st-theme-context.c b/src/st/st-theme-context.c index eb24212e1..5b066d269 100644 --- a/src/st/st-theme-context.c +++ b/src/st/st-theme-context.c @@ -311,11 +311,24 @@ static void st_theme_context_changed (StThemeContext *context) { StThemeNode *old_root = context->root_node; + g_autoptr (GPtrArray) old_nodes = NULL; + context->root_node = NULL; - g_hash_table_remove_all (context->nodes); + old_nodes = g_hash_table_steal_all_keys (context->nodes); g_signal_emit (context, signals[CHANGED], 0); + /* Force a run of the dispose() vfuncs of theme nodes so that their references + * into the theme CSS data get cleared. While theme nodes might outlive this + * function (in case buggy user code is holding a reference to them), the theme + * CSS data definitely gets freed after this function returns. + * + * Note that we can't do this before emitting ::changed because during the + * signal emission, StWidget needs to access the theme nodes (and therefore the + * theme CSS data) for its old/new theme node comparisons. + */ + g_ptr_array_foreach (old_nodes, (GFunc) g_object_run_dispose, NULL); + if (old_root) g_object_unref (old_root); } @@ -599,4 +612,4 @@ st_theme_context_get_resolution (StThemeContext *context) g_return_val_if_fail (ST_IS_THEME_CONTEXT (context), -1); return clutter_backend_get_resolution (context->clutter_backend); -} \ No newline at end of file +}